// 2013-9-12上午02:26:01  net.betou.trade.main.manager.agencyorproxy.impl.AgencyMngImpl.java

package net.betou.trade.main.manager.agencyorproxy.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.betou.common.hibernate3.Updater;
import net.betou.common.page.Pagination;
import net.betou.common.security.encoder.PwdEncoder;
import net.betou.common.security.encoder.SaltGenerator;
import net.betou.core.service.AgencyOrProxyListener;
import net.betou.trade.entity.main.AgentAndAdmins;
import net.betou.trade.entity.main.AgentAndAdminsExt;
import net.betou.trade.entity.main.Role;
import net.betou.trade.main.dao.agencyorproxy.AgencyDao;
import net.betou.trade.main.manager.AgentAndAdminsExtMng;
import net.betou.trade.main.manager.PictureMng;
import net.betou.trade.main.manager.agencyorproxy.AgencyMng;
import net.betou.trade.main.manager.role.AgencyRoleMng;
import net.betou.trade.role.setting.AgentFinderConfig;
import net.betou.trade.web.DBConstants;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author 叶装装
 */
@Service
@Transactional
public class AgencyMngImpl implements AgencyMng{

	@Transactional( readOnly = true )
	public Pagination getPage( AgentAndAdmins admin, String searchProperty, String searchValue, String orderProperty, String orderDirection, int pageNo, int pageSize, String filterStatus ) {
		Pagination pagination;
		if( admin.getSystem( ) ){ // 系统管理员，直接获取数据
			pagination = dao.getPage( false, false, true, null, searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, filterStatus );
		}else{

			AgentFinderConfig config = new AgentFinderConfig( admin );
			if( config.isSelf( ) ){ // 查询自己的
				pagination = dao.getPage( false, false, true, admin.getId( ), searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, filterStatus );
			}else{ // 深度查询
				pagination = dao.getPageByCriteria( searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, config.getDeepSQL( ) );
			}
		}

		return pagination;
	}

	@Transactional( readOnly = true )
	public AgentAndAdmins findById( Integer id ) {
		return dao.findById( id );
	}

	@Transactional( readOnly = true )
	public AgentAndAdmins findAgency( Integer id ) {
		return dao.findAgency( id );
	}

	@Transactional( readOnly = true )
	public AgentAndAdmins findBySelf( AgentAndAdmins admin, Integer id ) {
		if( admin.getSystem( ) ){
			return dao.findAgency( id );
		}
		return dao.findBySelf( admin.getId( ), id );
	}
	
	@Transactional( readOnly = true )
	public List< AgentAndAdmins > listAgencyToTreeForChild( Integer id ) {
		return dao.findAgencyList( id, null );
	}
	
	@Transactional( readOnly = true )
	public List< AgentAndAdmins > listAgencyToTreeForParent( AgentAndAdmins admin ) {
		if( admin.getSystem( ) ){
			return dao.findAgencyList( null, true );
		}
		
		return dao.findAgencyList( admin.getId( ), true );
	}
	
	@Transactional( readOnly = true )
	public List< AgentAndAdmins > listAccountToTreeForParent( AgentAndAdmins admin ){
		if( admin.getSystem( ) ){
			return dao.findAccountList( null, true );
		}
		return dao.findAccountList( admin.getId( ), true );
	}
	
	@Transactional( readOnly = true )
	public List< AgentAndAdmins > listAccountToTreeForChild( Integer id ){
		return dao.findAccountList( id, null );
	}

	public AgentAndAdmins [ ] deleteByIds( Integer [ ] ids ) {
		AgentAndAdmins [ ] beans = new AgentAndAdmins [ ids.length ];
		for ( int i = 0; i < ids.length; i++ ){
			beans[ i ] = dao.deleteById( ids[ i ] );
		}
		return beans;
	}

	public AgentAndAdmins update( Boolean disabled, String password, String email, String mobile, String intermediaName, AgentAndAdmins bean, AgentAndAdminsExt ext, Integer [ ] roleIds, String [ ] pic, Integer [ ] picIds ) {

		beforeUpdate( picIds, pic, bean );

		if( StringUtils.isNotBlank( password ) ){
			String loginSalt = salt.randomSalt( ); // 重新生成密码混淆

			bean.setSalt( loginSalt );
			bean.setPassword( pwdEncoder.encodePassword( password, loginSalt ) );
		}

		if( disabled == null ){
			bean.setDisabled( true );
		}else{
			bean.setDisabled( false );
		}

		bean.setEmail( StringUtils.isBlank( email ) ? null : email );
		bean.setMobile( StringUtils.isBlank( mobile ) ? null : mobile );
		bean.setIntermediaName( intermediaName );

		if( roleIds != null ){
			bean.getRoles( ).clear( ); // 清空角色

			for ( Integer id : roleIds ){
				Role role = mng.findById( id );
				bean.addToRoles( role );
			}
		}

		Updater< AgentAndAdmins > updater = new Updater< AgentAndAdmins >( bean );
		updater.include( "email" );
		updater.include( "mobile" );
		updater.include( "agencyOrProxy" );

		beforeUpdate( bean, updater );

		bean = dao.updateByUpdater( updater ); // 更新主表
		extMng.update( ext, bean ); // 更新附表

		return bean;

	}

	/**
	 * 保存机构，两种情况 1. 系统管理员添加的时候，需要增加两个默认角色 2. 非系统管理员添加的时候，不需要增加角色
	 */
	public AgentAndAdmins save( AgentAndAdmins currentAdmin, String ip, AgentAndAdmins bean, AgentAndAdminsExt ext, String [ ] pic ) {
		bean.setCreateIp( ip );

		String loginSalt = salt.randomSalt( );

		bean.setSalt( loginSalt );
		bean.setPassword( pwdEncoder.encodePassword( bean.getPassword( ), loginSalt ) );

		boolean system = currentAdmin.getSystem( ); // 查看是否是系统管理员，如果是，第一次的角色为系统默认的机构角色

		Role role;

		if( system ){
			role = mng.findAgencyByDefault( ); // 查找系统默认的机构角色
		}else{
			// 查看当前用户默认的机构角色
			role = mng.findAgencyBySelf( currentAdmin );
		}

		bean.saveToAgency( currentAdmin ); // 保存机构

		bean.addToRoles( role );
		dao.save( bean );
		extMng.save( ext, bean );

		afterSave( currentAdmin, bean, pic );

		return bean;
	}

	private void beforeUpdate( Integer [ ] picIds, String [ ] pic, AgentAndAdmins bean ) {
		if( picIds != null ){
			picMng.deleteByIds( picIds );
		}

		if( pic != null ){
			for ( String p : pic ){
				picMng.save( bean, p, null );
			}
		}
	}

	private void afterSave( AgentAndAdmins currentAdmin, AgentAndAdmins bean, String [ ] pic ) {

		// 先保存图片....
		if( pic != null ){
			for ( String p : pic ){
				picMng.save( bean, p, null );
			}
		}
		
		if( !isAgency( currentAdmin ) ){
			return;
		}
		
		for( AgencyOrProxyListener lis : listenerList ){
			lis.afterSave( bean );
		}
	}
	
	private boolean isAgency( AgentAndAdmins admin ){
		if( admin.getSystem( ) ){
			return true;
		}
		
		if( !admin.getJustAdmin( ) && admin.getAgencyOrProxy( ) ){
			return true;
		}
		
		return false;
	}
	
	private void beforeUpdate( AgentAndAdmins bean, Updater< AgentAndAdmins > updater ){
		Set< Role > roles = bean.getRoles( );
		if( roles != null && !roles.isEmpty( ) ){
			for ( Iterator< Role > it = roles.iterator( ); it.hasNext( ); ){
				Role r = it.next( );

				if( DBConstants.DEFINED_AGENCY_IDENTITY.equals( r.getIdentity( ) ) ){
					bean.setAgencyOrProxy( true );
					break;
				}

				if( DBConstants.DEFINED_PROXY_IDENTITY.equals( r.getIdentity( ) ) ){
					bean.setAgencyOrProxy( false );
					break;
				}

				if( StringUtils.isBlank( r.getIdentity( ) ) ){
					bean.setJustAdmin( true );
					updater.include( "justAdmin" );
					break;
				}
			}
		}
	}

	private List< AgencyOrProxyListener > listenerList;
	
	public void setListenerList( List< AgencyOrProxyListener > listenerList ) {
		this.listenerList = listenerList;
	}

	@Autowired
	private AgencyDao dao;

	@Autowired
	private SaltGenerator salt;

	@Autowired
	private PwdEncoder pwdEncoder;

	@Autowired
	private AgencyRoleMng mng;

	@Autowired
	private AgentAndAdminsExtMng extMng;

	@Autowired
	private PictureMng picMng;
	
}
